/*
 * @Description: 选项数据定义构造函数
 * @Author: HuiSir<https://gitee.com/huisir001>
 * @Date: 2025-08-15 17:39:56
 * @LastEditTime: 2025-08-15 23:25:51
 */

/* eslint-disable @typescript-eslint/no-explicit-any */

// 配置结构：键为任意PropertyKey，值为[label, value]元组
type OptionConfig<T> = Record<PropertyKey, [string, T]>;

// 从配置中提取键名类型
type ExtractCodes<C> = C extends Record<infer K, any> ? K : never;

// 从配置中提取值类型（元组第二个元素）
type ExtractValue<C> = C extends Record<any, [any, infer V]> ? V : never;

/**
 * 选项配置类（专注于逻辑实现，不处理复杂类型）
 * @template T 元组中第二个值的类型
 */
export class Options<T> {
  // 私有配置存储
  private _config: OptionConfig<T>;

  /**
   * 定义Options选项常量
   * @param config `{code:[label,value]}`代号对象，包含名称label与值value以及值代号code，value与label使用元组语法传入
   */
  constructor(config: OptionConfig<T>) {
    this._config = config;

    // 动态绑定属性
    (Object.keys(config) as (keyof OptionConfig<T>)[]).forEach((code) => {
      (this as Record<keyof OptionConfig<T>, T>)[code] = config[code][1];
    });
  }

  /**
   * 取选项列表
   */
  get options() {
    return Object.values(this._config).map((item) => ({
      label: item[0],
      value: item[1],
    }));
  }

  /**
   * 已知value取label
   */
  getLabel(value: T) {
    return this.options.find((opt) => opt.value === value)?.label || "";
  }
}

/**
 * 工厂函数（专门处理类型推断，返回带动态属性的实例）
 * @param config 配置对象（必须用as const增强推断）
 */
function createOptions<C extends OptionConfig<any>>(config: C) {
  // 从配置中自动推断值类型
  type T = ExtractValue<C>;
  // 返回实例，并断言为"Options<T> + 动态属性"的交叉类型
  return new Options<T>(config) as Options<T> & {
    [K in ExtractCodes<C>]: T;
  };
}

export default createOptions;
